﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using App.Domain;
using App.Web.ViewModels;
using AutoMapper;
using App.Core.Xml;
using App.Core.Extensions;
using App.Core.DB;
using System.IO;
using App.Core.Mail;
using System.Text;

using System.Web.Mvc;
using App.Web.Utility;

namespace App.Web.Utility
{
    public static class WebUtil
    {
        /// <summary>
        /// Populates the Session for an previously Authenticated User
        /// </summary>
        public static void ReLoginUser()
        {
            if (HttpContext.Current.User.Identity.IsAuthenticated && SessionCache.CurrentUser == null)
            {
                String userName = HttpContext.Current.User.Identity.Name;
                AppEntities context = new AppEntities();
                User user = context.Users.FirstOrDefault(U => String.Compare(U.UserName, userName, true) == 0);                
                if (user != null)
                {
                    ///Load Group and Group Permissions                                
                    //user.UserGroup = groupDAO.Get(user.GroupCode);                
                    UserViewModel userViewModel = null;
                    userViewModel = Mapper.Map<User, UserViewModel>(user, userViewModel);

                    ///Load Compnay Information, if Exists
                    LoadCompanyInfo(userViewModel, user, context);
                    SessionCache.CurrentUser = userViewModel;
                }
            }
        }
        /// <summary>
        /// Loads Company Information to the UserViewModel Object if user is a companys User
        /// </summary>
        /// <param name="userViewModel"></param>
        /// <param name="user"></param>
        /// <param name="context"></param>
        public static void LoadCompanyInfo(UserViewModel userViewModel, User user, App.Domain.AppEntities context)
        {
            if (user.UserContacts.Count > 0)
            {
                UserContact userContact = context.UserContacts.FirstOrDefault(P => P.UserID == user.ID);
                if (userContact != null && userContact.Contact.Company != null)
                {
                    Company company = userContact.Contact.Company;
                    userViewModel.Company = Mapper.Map<Company, CompanyViewModel>(company);
                }
            }
        }        
        public static String GetBooleanLabelID(String elementName, bool isEnabled)
        {
            if (isEnabled)
                return String.Format("{0}{1}_Yes", AppConstants.UI.DYNAMIC_CONTROL_PREFIX, elementName);
            else
                return String.Format("{0}{1}_No", AppConstants.UI.DYNAMIC_CONTROL_PREFIX, elementName);
        }

        public static bool IsTrue(String value)
        {
            return String.Compare(value, "Yes", true) == 0 ? true : false;
        }
        public static bool IsFalse(String value)
        {
            return String.Compare(value, "No", true) == 0 ? true : false;
        }
        /// <summary>
        /// Maps category definition to View Model
        /// </summary>
        /// <param name="productViewModel"></param>
        /// <param name="categoryDefinition"></param>
        public static void MapZGL(ProductViewModel productViewModel, string categoryDefinition)
        {
            App.Web.ViewModels.ZGL.Category.Category categoryLGL = XmlHelper.ToObject<App.Web.ViewModels.ZGL.Category.Category>(categoryDefinition);
            ///If Edit Mode of a Product
            if (!productViewModel.DynamicProperties.IsNullOrEmpty())
            {
                App.Web.ViewModels.ZGL.Product.Product productDefinition = XmlHelper.ToObject<App.Web.ViewModels.ZGL.Product.Product>(productViewModel.DynamicProperties);
                foreach (App.Web.ViewModels.ZGL.Category.ProductGroup group in categoryLGL.Group)
                {
                    foreach (App.Web.ViewModels.ZGL.Category.ProductGroupProperty property in group.Property)
                    {
                        setPropertyValue(property, productDefinition.Property);
                    }
                }
            }
            productViewModel.CategoryZGL = categoryLGL;
        }

        private static void setPropertyValue(ViewModels.ZGL.Category.ProductGroupProperty property, List<ViewModels.ZGL.Product.ProductProperty> sourceProperties)
        {
            ViewModels.ZGL.Product.ProductProperty sourceProperty = sourceProperties.FirstOrDefault(P => String.Compare(P.Name, property.Name, true) == 0);
            if (sourceProperty != null)
                property.Value = sourceProperty.Value;
        }
        /// <summary>
        /// Gets Formated Data for Display Purpose
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static String FormatData(object data)
        {
            if (data.GetType() == typeof(String))
                return NullHandler.GetString(data);
            else if (data.GetType() == typeof(DateTime))
                return NullHandler.GetDateTime(data).ToString(AppConstants.ValueOf.DATE_FROMAT_DISPLAY);
            else if (data.GetType() == typeof(decimal))
                return String.Format(AppConstants.ValueOf.DECIMAL_FORMAT, NullHandler.GetDecimal(data));
            else if (data.GetType() == typeof(bool))
                return NullHandler.GetBoolean(data) ? "Yes" : "No";
            else
                return NullHandler.GetString(data);
        }

        /// <summary>
        /// HtmlEncodes text and replaces newline with <br/> tags to create newline in web pages
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public static String FormatText(String text)
        {
            return text.HtmlEncode().Replace(Environment.NewLine, "<br />").Replace("\n", "<br />");
        }
        /// <summary>
        /// Reads HTML Template from File System
        /// </summary>
        /// <param name="templateFileName"></param>
        /// <returns></returns>
        public static String ReadEmailTemplate(String templateFileName)
        {
            String filePath = HttpContext.Current.Server.MapPath(templateFileName);
            if (File.Exists(filePath))
                return File.ReadAllText(filePath);

            return String.Empty;
        }
        /// <summary>
        /// Gets Currently Hosted Domain Address
        /// </summary>
        /// <returns></returns>
        public static String GetDomainAddress()
        {
            Uri uri = HttpContext.Current.Request.Url;
            String url = String.Format("{0}{1}{2}{3}", uri.Scheme, Uri.SchemeDelimiter, uri.Host, uri.Port == 80 ? String.Empty : ":" + uri.Port);
            //return String.Format("http://{0}", HttpContext.Current.Request.Url.Host);
            return url;
        }
        public static bool SendMail(String fromEmail, String toEmail, String bcc, String cc, String subject, String message)
        {
            bool isSent = false;
            try
            {
                if (ConfigReader.SendEmailThroughGmail)
                    isSent = MailManager.SendEmailThroughGmail(fromEmail, toEmail, subject, message);
                else
                    isSent = MailManager.SendMail(toEmail, cc, bcc, fromEmail, subject, message);
            }
            catch (Exception ex)
            {
                ///Log Failed Message
                AppEntities context = new AppEntities();
                if (context.IsConnected())
                {
                    EmailMessage email = new EmailMessage();
                    email.Subject = subject;
                    email.FromEmail = fromEmail;
                    email.ToEmail = toEmail;
                    email.CC = cc;
                    email.BCC = bcc;
                    email.Message = message;
                    email.IsSent = false;
                    email.Created = DateTime.Now;
                    email.AttemptedOn = DateTime.Now;
                    email.ErrorMessage = ex.Message;
                    email.StackTrace = ex.StackTrace;
                    if (SessionCache.CurrentUser != null)
                        email.UserID = SessionCache.CurrentUser.ID;
                    context.AddToEmailMessages(email);
                    context.SaveChanges();
                }                
            }
            return isSent;
        }

        /// <summary>
        /// Gets Product Dynamic Property Value from a Prepopulated Dynamic Property Collection
        /// </summary>
        /// <param name="groupName"></param>
        /// <param name="propertyName"></param>
        /// <param name="product"></param>
        /// <returns></returns>
        public static String GetPropertyValue(String groupName, String propertyName, ViewModels.ZGL.Category.Category dynamicProperties)
        {
            if (dynamicProperties != null && dynamicProperties.Group != null)
            {
                ViewModels.ZGL.Category.ProductGroup group = dynamicProperties.Group.FirstOrDefault(G => G.Name == groupName);
                if (group != null)
                {
                    ViewModels.ZGL.Category.ProductGroupProperty property = group.Property.FirstOrDefault(P => P.Name == propertyName);
                    if (property != null)
                        return property.Value;
                }
            }
            return "N/A";
        }

        /// <summary>
        /// Checks Whether an Uploaded file is a Valid Image File Or Not
        /// </summary>
        /// <param name="httpPostedFile"></param>
        /// <returns></returns>
        public static bool IsValidImageFile(HttpPostedFileBase httpPostedFile)
        {
            if (httpPostedFile.ContentLength > 0)
            {
                string extension = Path.GetExtension(httpPostedFile.FileName);
                return IsValidImageFileExtension(extension);
            }
            return false;
        }
        /// <summary>
        /// Checks for a valid file extension for an image.
        /// </summary>
        /// <param name="extension"></param>
        /// <returns></returns>
        private static bool IsValidImageFileExtension(string extension)
        {
            if (String.Compare(extension, ".jpg", true) == 0)
                return true;
            else if (String.Compare(extension, ".jpeg", true) == 0)
                return true;
            else if (String.Compare(extension, ".gif", true) == 0)
                return true;
            else if (String.Compare(extension, ".png", true) == 0)
                return true;
            return false;
        }
        /// <summary>
        /// Builds Company URL Routes and Saves them into the Database if forced
        /// </summary>
        /// <param name="forceRebuild"></param>
        /// <returns></returns>
        public static String BuildCompanyUrlRoutes(bool forceRebuild)
        {
            AppEntities context = new AppEntities();
            if (!context.IsConnected())
                return "undefined";

            Configuration config = context.Configurations.FirstOrDefault(P => String.Compare(P.Name, ConfigReader.CompaniesUrlConfigurationKey, true) == 0);
            if (config == null){
                config = new Configuration();
                config.Name = ConfigReader.CompaniesUrlConfigurationKey;
                context.Configurations.AddObject(config);
            }
            if(config.Value.IsEmpty() || forceRebuild)
            {
                var companies = context.Companies;
                StringBuilder sb = new StringBuilder(10);
                foreach (Company company in companies)
                {                    
                    company.CompnayUrl = company.Name.ToSeoUrl();
                    if (sb.Length == 0)
                        sb.Append(company.CompnayUrl);
                    else
                        sb.AppendFormat("|{0}", company.CompnayUrl);
                }
                if (sb.Length == 0)
                    sb.Append("undefined");
                if (forceRebuild)
                {
                    config.Value = sb.ToString();
                    context.SaveChanges();
                }
                return sb.ToString();
            }
            return config.Value;
        }
        /// <summary>
        /// Builds Content URL Routes and Saves them into the Database if forced
        /// </summary>
        /// <param name="forceRebuild"></param>
        /// <returns></returns>
        public static String BuildContentUrlRoutes(bool forceRebuild)
        {
            AppEntities context = new AppEntities();
            if (!context.IsConnected())
                return "undefined";

            Configuration config = context.Configurations.FirstOrDefault(P => String.Compare(P.Name, ConfigReader.ContentsUrlConfigurationKey, true) == 0);
            if (config == null)
            {
                config = new Configuration();
                config.Name = ConfigReader.ContentsUrlConfigurationKey;
                context.Configurations.AddObject(config);
            }
            if (config.Value.IsEmpty() || forceRebuild)
            {
                var contents = context.Contents;
                StringBuilder sb = new StringBuilder(10);
                foreach (Content content in contents)
                {
                    content.Url = content.Title.ToSeoUrl();
                    if (sb.Length == 0)
                        sb.Append(content.Url);
                    else
                        sb.AppendFormat("|{0}", content.Url);
                }
                if (sb.Length == 0)
                    sb.Append("undefined");
                if (forceRebuild)
                {
                    config.Value = sb.ToString();
                    context.SaveChanges();
                }
                return sb.ToString();
            }
            return config.Value;
        }
        /// <summary>
        /// Gets the IP Address of the Requested Client
        /// </summary>
        /// <returns></returns>
        public static string GetRemoteIPAddress()
        {
            return HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
        }
        /// <summary>
        /// Gets the Session Key of currently executing request
        /// </summary>
        /// <returns></returns>
        public static string GetSessionKey()
        {
            if(HttpContext.Current.Session != null)
                return HttpContext.Current.Session.SessionID;
            return String.Empty;
        }
        /// <summary>
        /// Insert blank company information at the time 
        /// fist fase company registration
        /// </summary>
        /// <returns></returns>
        public static int InsertBlankCompany(string companyName)
        {
            AppEntities _Context = new AppEntities();
            CompanyViewModel viewModel = new CompanyViewModel();

            viewModel.Name = companyName;
            viewModel.IndustryTypeID = Utility.ConfigReader.IndustryTypeID;
            viewModel.DistrictID = Utility.ConfigReader.DistrictID;
            viewModel.Address = "__UnKnown";
            viewModel.Phone = "__UnKnown";
            viewModel.IsActive = false;

            Company entity = new Company();
            entity = Mapper.Map<CompanyViewModel, Company>(viewModel, entity);
            _Context.AddToCompanies(entity);
            entity.CreatedOn = DateTime.Now;
            entity.ModifiedOn = DateTime.Now;
            entity.ActivationKey = System.Guid.NewGuid();
            entity.CompnayUrl = entity.Name.ToSeoUrl();
            _Context.SaveChanges();


            return entity.ID;
        }

        /// <summary>
        /// Insert initial information for a contact
        /// </summary>
        /// <returns></returns>
        public static int InsertInitialContact(string email, string firstName, string lastName, int companyID)
        {
            AppEntities _Context = new AppEntities();
            //CompanyViewModel viewModel = new CompanyViewModel();
            ContactViewModel contactViewModel = new ContactViewModel();

            contactViewModel.LastName = lastName;
            contactViewModel.FirstName = firstName;
            contactViewModel.Gender = "M";
            contactViewModel.EmailPersonal = email;
            contactViewModel.ReligionID = Utility.ConfigReader.ReligionID;
            contactViewModel.IsActive = "true";
            contactViewModel.IsDeleted = "false";
            contactViewModel.CompanyID = companyID;


            Contact entity = new Contact();
            entity = Mapper.Map<ContactViewModel, Contact>(contactViewModel, entity);
            _Context.AddToContacts(entity);
            _Context.SaveChanges();


            return entity.ID;
        }
    }
}